import React, { useEffect, useState, useRef } from 'react';
import { Button, message, Row, Col, Form } from 'antd';
import { formatMessage } from 'umi';
import PubSub from 'pubsub-js';
import Drawer from '@/zero/components/Drawer';
import Modal from '@/zero/components/Modal';
import styles from './index.less';

// Insert one space between two chinese characters automatically.
const fixTwoCNChar = (text) => {
  if (/^[\u4e00-\u9fa5]{2}$/.test(text)) {
    return text.split('').join(' ');
  }
  return text;
};

const Index = (props) => {
  const {
    type, // Drawer，Modal

    loading,

    formProps,
    defaultRowLayout,
    defaultColLayout,
    markModified = true, // 标记已修改（*）
    disabled,

    visible,
    defaultVisible = false,
    // eslint-disable-next-line
    beforeShow = (resolve, reject) => {
      resolve();
    },
    afterShow,

    footer, // 底部内容，当不需要默认底部按钮时，可以设为 footer={null}
    okText = formatMessage({ id: '保存' }),
    okButtonProps,
    onOk,
    onSubmit = (newValue, success) => {
      console.log('Submit:', newValue);
      success();
    },
    cancelText = formatMessage({ id: '取消' }),
    cancelButtonProps,
    onCancel,
    onClose,

    items = [],
    initialValue = {},
    children,

    onValuesChange,
    onDirtyChange,

    skipValidation,

    renderActions = ({ disabled: newDisabled, okButton, cancelButton, cancel }) =>
      newDisabled ? (
        <Button key="close" onClick={cancel}>
          {formatMessage({ id: '关闭' })}
        </Button>
      ) : (
        <>
          {cancelButton}

          {okButton}
        </>
      ),

    form: outerForm,

    dispatch,
    ...rest
  } = props;

  const [innerForm] = Form.useForm();

  const form = outerForm || innerForm;

  const [dirty, setDirty] = useState(false);

  const [stateVisible, setStateVisible] = useState(defaultVisible);

  const [innerLoading, setInnerLoading] = useState(false);

  useEffect(() => {
    const token = PubSub.subscribe(`${type}.destroyAll`, () => {
      setDirty(false);
      setStateVisible(false);
      setInnerLoading(false);
    });
    return () => {
      if (token) {
        PubSub.unsubscribe(token);
      }
    };
  }, []);

  useEffect(() => {
    if (onDirtyChange) {
      onDirtyChange(dirty);
    }
  }, [dirty]);

  useEffect(() => {
    form.resetFields();
  }, [JSON.stringify(initialValue)]);

  const closeWarned = useRef(false);

  const execOk = (submitProps = {}, newSkipValidation = skipValidation) => {
    const newPush = (finalRecord) => {
      const push = onOk || onSubmit;
      push(
        finalRecord,

        (content) => {
          if (content !== null) {
            message.success({
              key: 'KEY_FORM',
              content: content || `${formatMessage({ id: '操作成功' })}`,
              duration: 3.5,
            });
          }
          setDirty(false);
          setStateVisible(false);
          setInnerLoading(false);
          form.submit(); // 用以触发 Form.Provider => onFormFinish
        }, // success

        (content) => {
          if (content !== null) {
            message.error({
              key: 'KEY_FORM',
              content: content || `${formatMessage({ id: '操作失败' })}`,
              duration: 5,
            });
          }
          setInnerLoading(false);
        }, // error

        form,

        {
          ...submitProps,

          dirty,
          setDirty,

          innerLoading,
          setInnerLoading,
        },
      );

      setInnerLoading(true);
    };

    if (newSkipValidation) {
      const finalRecord = form.getFieldsValue();
      newPush(finalRecord);
    } else {
      form
        .validateFields()
        .then((finalRecord) => {
          newPush(finalRecord);
        })
        .catch((errorInfo) => {
          if (errorInfo.errorFields) {
            form.scrollToField(errorInfo.errorFields[0]?.name);
          } else {
            console.log(errorInfo);
          }
        });
    }
  };

  const execCancel = (e) => {
    if (dirty && e && e.target.nodeName.toUpperCase() === 'DIV' && !closeWarned.current) {
      message.warning({
        key: 'KEY_FORM',
        content: formatMessage({ id: '数据未保存' }),
        duration: 3.5,
      }); // 点击遮罩层时触发

      closeWarned.current = true;
      setTimeout(() => {
        closeWarned.current = false;
      }, 1500);
    } else {
      setDirty(false);
      setStateVisible(false);

      const newOnClose = onCancel || onClose;
      if (newOnClose) {
        newOnClose(e);
      }
    }
  };

  const Element = type === 'Modal' ? Modal : Drawer;

  const newItems = typeof items === 'function' ? items({ disabled }) : items;

  return (
    <>
      {visible === undefined && (
        <span
          onClick={() => {
            new Promise((resolve, reject) => {
              beforeShow(resolve, reject, form);
            }).then(() => {
              setStateVisible(true);
              if (afterShow) {
                afterShow(form);
              }
            });
          }}
        >
          {typeof children === 'function' ? children({ form, disabled }) : children}
        </span>
      )}

      <Element
        {...rest}
        visible={visible !== undefined ? visible : stateVisible}
        onClose={execCancel}
        afterClose={() => {
          form.resetFields();
        }}
        footer={
          footer === null
            ? null
            : renderActions({
                disabled,
                dirty,
                form,

                ok: execOk,
                okButton: (
                  <Button
                    loading={loading !== undefined ? loading : innerLoading}
                    type="primary"
                    {...okButtonProps}
                    onClick={() => {
                      execOk();
                    }}
                  >
                    {fixTwoCNChar(okText)}
                    {markModified && dirty && <span style={{ marginLeft: 5 }}>*</span>}
                  </Button>
                ),

                cancel: execCancel,
                cancelButton: (
                  <Button
                    style={{
                      marginRight: 8,
                    }}
                    {...cancelButtonProps}
                    onClick={execCancel}
                  >
                    {cancelText}
                  </Button>
                ),
              })
        }
      >
        <div className={styles.dm}>
          <Form
            layout="vertical"
            form={form}
            {...formProps}
            onValuesChange={(changedValues, allValues) => {
              setDirty(true);
              if (onValuesChange) {
                onValuesChange(changedValues, allValues);
              }
            }}
            initialValues={initialValue}
          >
            <Row gutter={16} {...defaultRowLayout}>
              {newItems.map((item, index) => (
                <Col key={index} span={24} {...defaultColLayout} {...item.colLayout}>
                  {item.field ? (
                    <Form.Item {...item} name={item.name || item.field}>
                      {item.child}
                    </Form.Item>
                  ) : (
                    item.child
                  )}
                </Col>
              ))}
            </Row>
          </Form>
        </div>
      </Element>
    </>
  );
};

export default Index;
